En 1972 Colmovaur lo escribió en Fortran en una máquina IBM. Posteriormente en Edimburgo se escribió en código de máquina en una PDP.
>Valioso(oro).Valioso es un predicado, Oro es el elemento (constantes en minúsculas).
>Valioso.Este predicado no tiene elementos, tiene aridad 0.
>Valioso(plata). >Valioso(bronce)."La plata es valioso", "el bronce es valioso". Todos estos predicados se escriben en un "programa" de Prolog.
Tras "correr" el programa, se pueden hacer estas consultas:
?- Valioso(oro). ¿Es valioso el oro? Esta es una meta Yes Si, es la respuesta ?- Valioso(X.). X es una variable, por ello va en mayúscula X=oro; Esta es una respuesta. Al agregar el punto y coma se le X=plata; está pidiendo otra respuesta que satisface la meta X=bronce; no Cuando ya no encuentra más respuestas responde con "no".Programa
En el programa se ponen marcas acerca de los predicados que ya han servido de respuesta. Al resatisfacer la meta, las marcas se acumulan. Al solicitar una meta nueva las marcas se "olvidan". A este mecanismo se le conoce como algoritmo de Robinson.
Ejemplos:
>Le_gusta(juan,maria). A Juan le gusta María >Le_gusta(pedro,carla). >Le_gusta(jorge,maria). A estos predicados (de aridad 2) también se les conoce como hechos. ?- Le_gusta(X,maria). Meta: ¿A quién le gusta María? X=juan; X=jorge; no ?- Le_gusta(X,Y). Responde con todas las combinaciones. le_gusta_por(juan,maria,ojos grandes). A Juan le gusta María por sus grandes ojos. Tiene Aridad 3.Programa
>Valioso(bronce). >Valioso(X):-X=oro. Si X=oro entonces X es valioso. >Valioso(plata). ?- Valioso(oro). Yes; noPrograma
Otros ejemplos:
>alguien_es_inteligente. Un predicado de aridad 0 >alumno(X,inteligente). X es alumno inteligenteAsí se podría generar una lista de juegos con todas las combinaciones:
>Nino(1). >Nino(2). >Nino(3). >Nino(4). >Nino(5). >Nino(6). >Juegan(X,Y):-nino(X), nino(Y), X<>Y, write(X, " juega vs. ", Y), nl.Dentro de una declaración como la anterior a X y a Y se les conocen como parámetros formales. El punto y coma (;) representa un OR lógico. La coma (,) representa un AND lógico. "nl" representa un código de "nueva linea".
?- Juegan(X1,Y1). 1 juega vs. 2; ... 6 juega vs. 5; noPrograma
Dentro de la meta a X1 y a Y1 se les conoce como parámetros de meta.
>Pinta:-write("hola"), fail. ?- Pinta. holaSolo está un "hola" por que el fail no satisface predicados de entrada-salida.
"not" es la negación del predicado. Ejemplo:
"El barbero es el que rasura a todas las personas que no se rasuran" >Rasura(juan,juan). >Rasura(barbero,X):-not(Rasura(X,X)). ¿Quién rasura a Juan? ?- Rasura(X,juan). X=juan; no ¿Quién rasura a Pedro? ?- Rasura(X,pedro). X=barbero; no ¿Quién rasura al barbero? ?- Rasura(X,barbero). Se queda sin memoria.Programa
Prolog discrimina mayúsculas y minúsculas sólo en la primera letra.
>Le_gusta(juan,maria). >Le_gusta(pedro,carla). ?- Le_gusta(_,X). X=maria; X=carla; no
>Pred1(nombre, Gustos(leer,escribir,nadar)). ?- Pred1(X,Y). X=nombre Y=Gustos(leer,escribir,nadar); Y se instancia al predicado "Gustos". no no ?- Pred1(X,Y(Q,R,S)). Si es válido en Prolog pero no en TurboProlog. Esto es porque TurboProlog es tipificado.Ejemplos:
>Hermana(X,Y):-Sexo(X,femenino), Padre(X,Z), Padre(Y,Z), X<>Y. >Suma(X,Y,Z):-Z is X+Y. >Igual(X,Y):-X=Y.
, AND ; OR \= Distinto en Prolog is Igualdad en Prolog <> Distinto en TurboProlog = Válido en TurboProlog con las siguientes reglas: X=4 Si X está instanciado se realiza una comparación. Si X no está instanciado entonces se realiza la instancia.Ejemplo:
>Pop(usa,203). >Pop(india,548). >Pop(china,800). >Pop(brasil,108). >Area(usa,3). >Area(india,1). >Area(china,4). >Area(brasil,3). >Density(X,Y):-Pop(X,P),Area(X,A), Y is P/A. ?- Density(china,X). x=200Programa
Otro ejemplo:
>Padre(juan,luis). >Padre(juan,pedro). >Hermanos(luis,andres). >Hermanos(luis,joaquin). >Madre(maria,carmen). >Madre(laura,marta). ?- Padre(X,Y), fail. X=juan Y=luis X=juan Y=padre no ?- Padre(juan,pedro), hermanos(luis,jorge), madre(maria,carmen). si Primero se ejecuta Padre(juan,pedro) y responde si no Como hermanos(luis,jorge) falla, regresa un no y ya no se ejecuta la última.
>repeat. Función de salida, condición terminal. No hace nada. >repeat:-repeat. Función recursiva, al solicitar una nueva meta se limpian las marcas.Al no guardar variables no se le acaba la memoria ya que no debe de "regresar".
>Escribe:-repeat,write("hola"),nl,fail. ?-Escribe. hola ?-repeat hola ...Programa
Un ejemplo de la recursión es la función factorial. En el factorial 0!=1 es la condición de salida, mientras que n!=n*(n-1)! es el predicado recursivo.
Una definición circular no tiene condición de salida y se le acaba la memoria. Ejemplo:
>Padre(X,Y):-Hijo(Y,X). >Hijo(A,B):-Padre(B,A).
[] Es una lista vacía, no tiene elementos.
[a,b,c] Es una lista de tres elementos. "a" es la cabeza de la lista, el primer elemento. [b,c] es el "resto", es una lista con los demás elementos.
Ejemplos:
[a,b,c,[X,Z,Y]] [1,a,Z,[a],b,[c,[d,[e]]]] >P([1,2,3]) El predicado P es una lista de tres elementos. ?-P([X|Y]). X=1 X es la cabeza Y=[2,3] Y es el resto ?-P([X,Y|Z]). X=1 Y=2 Z=[3]Ejemplo:
>Member(X,[X|_]). Condición de salida >Member(X,[_|Y]):-Member(X,Y). Predicado recursivo ?-Member(a,[a,b,c]). X=a yes ?-Member(a,[b,a,c]). X=a no Y=[a,c] ?-Member(a,[a,c]). yesPrograma
Ejemplo:
>P([1]). ?-P([X|Y]). X=1 Y=[]Ejemplo:
>Imprime_lista([]). >Imprime_lista([X|Y]):-write(X),nl,Imprime_lista(Y). ?- Imprime_lista([a,b,c]). a b cPrograma
Ejemplo:
Q - You are a computer A - I am not a computer Q - Do you speak french A - no, I speak german >Change(You,I). >Change(are,[am,not]). >Change(french,german). >Change(do,no). >Change(X,X). >Alter[[],[]). >Alter([H|T],[X,Y]):-Change(H,X),Alter(T,Y). ?- Alter(You,are,a,computer],Z). H=You T=[are,a,computer] Z=[X,Y] ?- Change(You,X) X=I ?- Alter([are,a,computer],Y) H=are T=[a,computer] Y=[X,Y] ?-Change(are,X) X=[am,not] ?-Alter([a,computer],Y) . . .
>Member(X,[X|_]):-!,fail. >Member(X,[_|Y]):-Member(X,Y).Da la primera solución que encuentra y luego termina.
Turbo Prolog es un compilador/intérprete orientado a tipos, por ello, antes de usar una variable debe ser declarada. Un intérprete checa la sintáxis antes de ejecutar cada línea, por eso es más lenta su ejecución a diferencia de un programa compilado. El intérprete es fácil de debuggear (modificación de los valores de las variables durante la ejecución).
Dominios posibles: symbol, string, integer, real, symbol* (lista de símbolos), integer* (lista de enteros).
Domains nombre,direccion,telefono=string edad=integer Predicates imprime repeat persona(nombre,direccion,telefono,edad) Clauses imprime:-persona(X,Y,Z,E), write(X),nl, write(Y),nl, write(Z),nl, write(E),nl,fail. repeat. repeat:-repeat. persona("juan","alabama 1","123",23). persona("pablo","alabama 2","23123",24). persona("maria","alabama 3","343123",20). Goal imprime.Programa
Borra un hecho o predicado. Hablando propiamente lo inhibe. Ejemplo:
Prolog: Suicidio:-repeat, retract(_), fail. TurboProlog: retralall(_).Ejemplo de conjugación de verbos regulares:
/* Conjugación de verbos */ Domains Lista=string* Predicates pide_verbo member(Symbol,Lista) encuentra_sufijo(string,string,integer) encuentra_prefijo(integer,string,string) toma_elemento(lista,string) conjuga(symbol,string,string) Goal clearwindow,pide_verbo. Clauses toma_elemento([],_):-nl,!. toma_elemento([Head|Tail],Prefijo):-write(Prefijo,Head),nl, toma_elemento(Tail,Prefijo). pide_verbo:-write("Dame un verbo regular "),readln(Verbo), str_len(Verbo,LongVerbo),encuentra_sufijo(Verbo,Sufijo2,2), Numpref=LongVerbo-2,encuentra_prefijo(Numpref,Verbo,Prefijo),!, conjuga(preterito,Prefijo,Sufijo2),readchar(_),!,nl, conjuga(presente,Prefijo,Sufijo2),readchar(_),!,nl, conjuga(futuro,Prefijo,Sufijo2),readchar(_),!,nl, pide_verbo. pide_verbo. encuentra_prefijo(Numero,Palabra,Prefijo):-frontstr(Numero,Palabra,Prefijo,_). encuentra_prefijo(_,_,""). encuentra_sufijo(Palabra,Sufijo,Cuantos):-str_len(Palabra,Longitud), Longitud>=(Cuantos+1),PosInicial=Longitud-Cuantos, frontstr(PosInicial,Palabra,_,Sufijo). encuentra_sufijo(_,"",_). conjuga(preterito,Prefijo,ar):-toma_elemento([é,astes,ó,amos,astíis,aron],Prefijo). conjuga(presente,Prefijo,ar):-toma_elemento([o,as,a,amos,aís,an],Prefijo). conjuga(futuro,Prefijo,er):-toma_elemento([o,es,e,emos,eís,en],Prefijo).Programa
Segunda versión del programa Member
1.-Considere el siguiente programa:
a:-b,write("Exito"). a:-write("Falla"). b:-c(X),d(X),!,e(X),f(X). b. c(1). c(2). c(3). d(3). e(1). e(2). f(1).Si se pide al intérprete la meta ?-a. ¿Qué responde el sistema? Describase paso a paso el funcionamiento de Prolog para resolverlo.
2.-Supóngase que se tiene una lista: [a,b,c,d,e,f,g], háganse los siguientes predicados recursivos:
3.-Supóngase que tenemos el siguiente predicado:
delete(_,[],[]). delete(Head,[Head|Tail],Tail). delete(Token,[Head|Tail],[Head|Result]:-delete(Token,Tail,Result).Este predicado remueve sólo la primera ocurrencia de un elemento específico dentro de una lista. Escríbase un predicado recursivo que remueva todas las ocurrencias de un elemento en una lista. Ejemplo:
?- nuevo_del(a,[a,c,b,a,d,a],X). X=[c,b,d]Tarea 1 Programa 3
SHRLOU (Escrito por Winograd y Weizenbaum en 1972) Entendía semántica y sintáxis, es decir lenguaje natural. Realizaba acciones sobre su microcosmos: "Poner un cubo sobre la esfera", "poner una pirámide bajo la mesa".
Reglas de producción: Backward chaining (encadenamiento hacia atrás) y Forward chaining (encadenamiento hacia adelante). Siguen los If-Then es decir causas y efectos.
Frames (Minsk.) Se topa con el problema de ramificación de información. Información arquetípica. No se puede describir algo al 100%. No se usa ya que puede dar información irrelevante.
El sistema experto debe poder decir qué hizo y cómo lo hizo. Debe ser capaz de "recordar" los datos ya dados y usarlos; ya sean estos atemporales (nombre) o temporales (temperatura).
Sistema experto de Mecánica automotriz
2 M 1 B R A V E 4 R Q K U 3 R E A l I Z E T T E
a puede valer 1 m puede valer 13 o puede valer 24 "amo" valdría 38.Pero pueden existir colisiones:
o puede valer 24 m puede valer 13 a puede valer 1 "oma" valdría 38.Por lo que no se podría distinguir entre una y otra. Una solución es asignar peso a la posición:
amo = 1 + 13 * 2 + 24 * 3 = 99 oma = 24 + 13 * 2 + 1 * 3 = 53A este tipo de asignación de valores se le conoce como función Hash.
Program BusquedaBinaria; Const NumeroDeDatos=100; Type str80 = string[80]; str20 = string[20]; RecDic = record palabra:str20; end; Var cadena:str80; i,j,k,m:integer; j1:real; flag:boolean; NombreEnArreglo:str80; Diccionario:RecDir; Entrada,Salida:file; Procedure BusquedaLineal(cadena:str80); BEGIN flag:=false; Assign(Entrada,"Dic.txt"); Reset(Entrada); m:=filesize(Entrada); for i:=1 to m do begin read(Entrada,Diccionario); NombreEnArreglo:=Diccionario.palabra; if NombreEnArreglo=cadena Then flag:=TRUE; end; if flag=TRUE Then writeln("Encontrado!"); close(Entrada); END; Procedure Busca(cadena:str80); BEGIN flag:=FALSE; k:=0; Assign(Entrada,'Dic.txt'); Reset(Entrada); m:=filesize(Entrada); repeat j:=(k+m) div 2; seek(Entrada,j); read(Entrada,Diccionario); NombreEnArreglo:=Diccionario.palabra; if cadena=NombreEnArreglo then begin flag:=TRUE; writeln("Encontrado en la posición ",j+1); end; if cadenaDiccionario muestraNombreEnArreglo then k:=j+1; if k>m then begin j:=0; writeln("Nombre no encontrado"); flag:=TRUE; end; until flag=TRUE; close(Entrada); END; BEGIN clrscr; write(´Dame la palabra: ´); readln(cadena); Busca(cadena); BusquedaLineal(cadena); END.
Inicio ---| |----------- | 1| 2 3 4| 5 6| | | | | --| | 7| 8 9|10|11|12| | -----| | | | |13 14 15|16|17|18| |--| | | | | | |19|20|21 22|23|24| | | |-----| | | |25|26 27 28 29|30| | |-----| |--| | |31 32 33 34 35 36| --| |------------ FinalOtros Ejemplos:
Impresión de una lista: print([]). print([X|Y]):-write(X),nl,print(Y). Toma dos listas y únelas: append([],List,List). append([X|List1],List2,[X|List3]):-append([List1,List2,List3). ¿Cuántos elementos tiene una lista? list_length([],0). list_length([_|Tail],Number):-list_length(Tail,Count),Number=Count+1. Añade un elemento a la cabeza de la lista: add_element(X,List,[X|List]). Escribe una lista alrevés: Clauses reverse_list([],[]). reverse_list([Head|Tail],List):-reverse_list(Tail,X),append(X,[Head,List]). Domains list=char* Predicates reverse_list(list,list). append(list,list,list). Librerías para el uso de cadenas: wordcount("",0). wordcount(Str,Count):-!,strsfind(Str," ",Pos),frontstr(Pos,Str,_,Newstr), wordcount(Newstr,Oldcount), Count=Oldcount+|. strsfind(Srcstr,Substr,Pos):-str_len(Srestr,Size),str_len(Substr,Ssize), matchs(Srestr,Substr,Ssize,Sub1),Pos=Size-(Ssize+Sub1)+1. matchs(Str1,_,_,_). matchs(Str1,Str2,Size,Sub1):-frontstr(Size,Str1,Firts,Rest),First=str2,str_len(Rest,Sub1). matchs(Str1,Str2,Size,Sub1):-ftontchar(Str1,_,Rest),!,matchs(Rest,Str2,Size,Sub1). Predicates strsfind(string,string,integer). wordcount(string,integer). matchs(string,string,integer,integer).
function factorial(N:integer):integer; begin if N=0 then factorial:=1; else factorial=N*factorial(N-1); end;En Prolog:
factorial(0,1). factorial(N,FactN):-N>0,M=N-1,factorial(M,FactM),FactN=N*FactM.
En Pascal:
for i:=1 to 5 writeln(i+" "+sqrt(i));En Prolog:
print_square_root(I):-I>5,!. print_square_root(I):-R=sqrt(I),write(I),write(" "),write(R),nl,NewR=I+1,print_square_root(NewR).
perro(X):-canino(X). canino(X):-perro(X).No funciona ya que no tiene salida. Para evitar este tipo de situaciones existe el operador bicondicional (-:-):
prove(Goal):-call(Goal). prove(GoalA):-(GoalA-:-GoalB),call(GoalB). prove(GoalB):-(GoalA-:-GoalB),call(GoalA).Con esto podemos redefinir perro y canino:
perro(fido) canino(rolf) perro(X)-:-canino(X). ?- perro(X) X=fido ?- canino(X) X=rolf ?- prove(perro(X)) X=fidoEjemplo, derivadas:
d(X,X,1). d(C,X,0):-atomic(C). d(u+v,X,A+B):-d(u,X,A),d(v,X,B). d(u*V,X,B*u+A*V):-d(u,X,A),d(v,X,B). d(n*X,X,n):-atomic(n).
Domains integerlist=integer* Predicates writelist(integerlist) write5(integerlist,integer) Clauses writelist(NL):-nl,write5(NL,0),nl. write5(TL,5):-!,nl,write5(TL,0). write5([H|T],N):-!,write(H," "),NL=N+1,write5(T,NL). write5([],_).
Domains file=entrada Clauses openread(entrada,"datos.dat"). filestr(entrada,Texto).
También existen nombres de "archivos" especiales que se refieren a dispositivos (DFN. Device File Name), estos son:
Domains file=destination Goal openwrite(destination,"mydata.dat"), writedevice(destination), write("Hola"), writedevice(screen), closefile(destination).Otro ejemplo:
Domains file=myfile Predicates readloop Goal openwrite(myfile,"try.txt"), writedevice(myfile),readloop,closefile(myfile). Clauses readloop:-readchar(X),X<>'#',!,write(X),readloop. readloop.
Domains file=input Predicates inspect_position Goal readln(Filename), openread(input,Filename),inspect_position. Clauses inspect_position:-readdevice(keyboard),nl,write("position number?"), readreal(X),readdevice(input),filepos(input,X,0),readchar(Y), write("char is ",Y),inspect_position.
Escribe un archivo en pantalla en forma espiral
Valor Caracteres Fondo 0 Negro Negro 7 Blanco Negro 112 Negro Blanco
Valor Color 0 Negro 16 Azul 32 Verde 48 Cyan 64 Rojo 80 Morado 96 Cafe 112 Blanco
Valor Color 0 Negro 1 Azul 2 Verde 3 Cyan 4 Rojo 5 Morado 6 Cafe 7 Blanco 8 Gris 9 Azul claro 10 Verde claro 11 Cyan claro 13 Morado claro 14 Amarillo 15 Blanco de alto contraste
Con esta predicado se puede abrir un directorio:
directorio:-makewindow(32,31,30,"Directorio",10,10,10,65),clearwindow,dir(" ","*.*",_,1,1,1), removewindow.Editor de texto en Turbo Prolog.
ex("v","enb",[],"p"). ex("v","malb",["malbaratar"],"sb"). ex("v","abe",["abecedario","adedul","abeja"],"p"). ex("v","bicio",[],"s"). ex("v","b","cav",["caviar","cavilar","cavar"],"p"). mensaje:-(1,Prefijo,Palabra,Letra):-makewindow(.0,79,79,"Diagnóstico",12,1,8,46),clearwindow, writedevice(screen),write("Las palabras que empiezan con "),write(Prefijo),nl, write("se escriben con "),write(Letra),nl,nl,write("La palabra: "),write(Palabra), write("está mal escrita."). editor:-makewindow(31,31,30,"¿Archivo a editar?",10,10,10,65),clearwindow, trap(dir(" ","*.*",FileName,1,1,1),E,error(E)),FileName<>"",file_str(FileName,Str), removewindow,makewindow(32,112,126,"Editor",3,3,22,75),clearwindow,EditMode=1,Indent=0, Insert=1,TextMode=1,edit(Str,Out," ",FileName,"Oprima F10 para continuar o ESC para cancelar",0,"C:\prolog.hlp",EditMode,Indent,Insert,TextMode,_),lineinput(10,10,50,21,14, "Nombre del archivo a salvar: ",FileName,NewFileName),file_str(NewFileName,Out), removewindow. directorio:-makewindow(32,31,30,"Directorio",10,10,10,65),clearwindow,dir(" ","*.*",_,1,1,1), removewindow. shell_dos:-system(""). despliega(Letrero,FileName,Attrib,FAttrib):-EditMode=0,Indent=0,TextMode=0, trap(file_str(FileName,Str),E,error(E)),makewindow(3,Attrib,FAttrib,Letrero,4,3,19,75), clearwindow,edit(Str,_,FileName,FileName,"Oprima ESC para salir",0,"C:\prolog.hlp", EditMode,Indent,Insert,TextMode,_,_),removewindow.Predicado que lee un archivo y lo despliega en pantalla:
file_str(Nombre,Str),write(Str).Predicado que lee un archivo caracter por caracter y lo despliega en pantalla:
readloop:-readchar(X),X<>eof(Ent),write(X),!,readloop. goal openread(Ent,N),readdevice(Ent),readloop,closefile(Ent).
String_Chr("",[]). String_Chr(S,[H|T]):-fontchar(S,H,S1),String_Chr(S1,T).
fronttoken(Str,Token,RestoStr). fronttoken("Hola cara de bola",T,R) T=Hola (Symbol) R="cara de bola"Este ejemplo transforma una cadena a una lista de símbolos:
String_Token(S,[H|T]):-fronttoken(S,H,S1),!,Strinf_Token(S1,T). String_Token(_,[]).
frontstr(#,cadena,cad1,resto) frontstr(4,"Manuel",A,B). A="Manu" B="el"
concat("mkdir ",DestinoDir,Comando). system(Comando,0,_).
Domains X=integer Predicates M(X) Busca(X) Clauses M(1):-write(1). M(X):-(X-1) MOD 3=0,X MOD 2=0,write(X," "). M(X). Busca(Z):-M(Z),W=Z-1,W>0,!,Busca(W). Goal Busca(50)
initgraph(GrDriver,GrMode,NewD,NewM,Path) GrDriver: Manejador gráfico, 0 para que lo detecte solo. NewD y NewM son variables que se instancian con el tipo de gráficos que se están usando.